﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EmbeddedLanguage
{
    public static class StringEx
    {
        public static string SubstringBefore(this string val, string Search)
        {
            if(val==null) return null;
            int iPos = val.IndexOf(Search);
            if (iPos < 0) return val;
            return val.Substring(0, iPos);
        }

        public static string SubstringBeforeLast(this string val, string Search)
        {
            if (val == null) return null;
            int iPos = val.LastIndexOf(Search);
            if (iPos < 0) return val;
            return val.Substring(0, iPos);
        }

        public static string SubstringAfter(this string val, string Search)
        {
            if (val == null) return null;
            int iPos = val.IndexOf(Search);
            if (iPos < 0) return string.Empty;
            return val.Substring(iPos + Search.Length);
        }

        public static string SubstringAfterLast(this string val, string Search)
        {
            if (val == null) return null;
            int iPos = val.LastIndexOf(Search);
            if (iPos < 0) return string.Empty;
            return val.Substring(iPos + Search.Length);
        }

        public static PartialRemoveState RemoveBetween(this string val, string Search)
        {
            return new PartialRemoveState(val, Search);
        }

        public static PartialRemoveState RemoveBetweenEvery(this string val, string Search)
        {
            return new PartialRemoveState(val, Search)
            {
                All = true,
            };
        }

        public static PartialReplaceBetweenState ReplaceBetween(this string val, string Search)
        {
            return new PartialReplaceBetweenState(val, Search);
        }

        public static PartialBetweenState SubstringBetween(this string val, string Search)
        {
            return new PartialBetweenState(val, Search);
        }

        public static string Repeat(this string val, int Number)
        {
            if (Number > 2)
            {
                var sb = new StringBuilder();
                for (int i = 0; i < Number; i++)
                {
                    sb.Append(val);
                }
                return sb.ToString();
            }
            if (Number == 2) return val + val;
            if (Number == 1) return val;
            if (Number == 0) return string.Empty;
            return null;
        }
    }

    public class PartialRemoveState
    {

        private string _OriginalString;
        private string _SearchStart;

        public bool All { get; set; }

        public PartialRemoveState(string OriginalString, string SearchStart)
        {
            _OriginalString = OriginalString;
            _SearchStart = SearchStart;
        }
        
        public string And(string Search)
        {
            if (this.All) return this.AndAll(Search);
            string before = _OriginalString.SubstringBefore(_SearchStart);
            string afterStart = _OriginalString.SubstringAfter(_SearchStart);
            if (string.IsNullOrEmpty(afterStart)) return _OriginalString;
            string afterSearch = afterStart.SubstringAfter(Search);
            if (string.IsNullOrEmpty(afterSearch) && !_OriginalString.EndsWith(Search)) return _OriginalString;
            return before + afterSearch;
        }

        private string AndAll(string Search)
        {
            string returnS = _OriginalString;
            while (!string.IsNullOrEmpty(returnS.SubstringBetween(_SearchStart).And(Search)))
            {
                string before = returnS.SubstringBefore(_SearchStart);
                string afterStart = returnS.SubstringAfter(_SearchStart);
                //if (string.IsNullOrEmpty(afterStart)) return _OriginalString;
                string afterSearch = afterStart.SubstringAfter(Search);
                if (string.IsNullOrEmpty(afterSearch) && !returnS.EndsWith(Search)) return returnS;
                returnS = before + afterSearch;
            }
            return returnS;
        }
    }

    public class PartialBetweenState
    {
        //private bool _StartAtLast;
        private string _OriginalString;
        private string _SearchStart;

        public PartialBetweenState(string OriginalString, string SearchStart)
        {
            _OriginalString = OriginalString;
            _SearchStart = SearchStart;
        }

        

        //public string And(string Search)
        //{
        //    string before = _OriginalString.SubstringBefore(_SearchStart);
        //    string afterStart = _OriginalString.SubstringAfter(_SearchStart);
        //    if (string.IsNullOrEmpty(afterStart)) return _OriginalString;
        //    string afterSearch = afterStart.SubstringAfter(Search);
        //    if (string.IsNullOrEmpty(afterSearch) && !_OriginalString.EndsWith(Search)) return _OriginalString;
        //    return before + afterSearch;
        //}

        public string And(string Search)
        {
            string afterStart = _OriginalString.SubstringAfter(_SearchStart);
            return afterStart.SubstringBefore(Search);
        }

        public string AndLast(string Search)
        {
            string afterStart = _OriginalString.SubstringAfter(_SearchStart);
            return afterStart.SubstringBeforeLast(Search);
        }
    }

    public class PartialReplaceBetweenState
    {
        private string _OriginalString;
        private string _SearchStart;
        private string _SearchEnd;

        public PartialReplaceBetweenState(string OriginalString, string SearchStart){
            this._OriginalString = OriginalString;
            this._SearchStart = SearchStart;
        }

        public PartialReplaceBetweenState And(string Search)
        {
            this._SearchEnd = Search;
            return this;
        }

        public String Set(string newValue)
        {
            string returnS = _OriginalString.SubstringBefore(this._SearchStart);
            returnS += (this._SearchStart + newValue);
            string restS = _OriginalString.SubstringAfter(this._SearchStart);
            restS = restS.SubstringAfter(this._SearchEnd);
            returnS += this._SearchEnd + restS;
            return returnS;
        }
    }
}
